#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <string.h>
#include <math.h>
#include <mpi.h>
#include <stdio.h>
#include <time.h>

#define         X_RESN  800
#define         Y_RESN  600
#define         NUM_PROCS 3

typedef struct complextype
        {
        float real, imag;
        } Compl;

int main(int argc, char** argv)
{

        Window          win;
        unsigned
        int             width, height,
                        x, y,
                        border_width,
                        display_width, display_height,
                        screen;

        char            *window_name = "Mandelbrot Set", *display_name = NULL;
        GC              gc;
        unsigned
        long            valuemask = 0;
        XGCValues       values;
        Display         *display;
        XSizeHints      size_hints;
        Pixmap          bitmap;
        XPoint          points[800];
        FILE            *fp, *fopen ();

  char            str[100];
        XSetWindowAttributes attr[1];

        double end, start;
        Compl   z, c;
        int i, j,b, p, k,m,n,index, color, row,row_rec, rank, size,tag = 0;
             int u, point,dummym,dummys;
        float   lengthsq, temp;
        int send=0; int recv=0,send1;
        int recvbuf[1930000];

                int temp_recvbuf[193000];

                int sendbuf[193000];
                MPI_Status status;
                MPI_Init(&argc,&argv);
                MPI_Comm_size(MPI_COMM_WORLD, &size);
                MPI_Comm_rank(MPI_COMM_WORLD, &rank);
                MPI_Barrier(MPI_COMM_WORLD);


                if ( rank==0)
                { row=0;
                  printf("the master process \n");
             

                for (m=0;m<size-1;m++)
                  {
                        send=row;
                        MPI_Send(&send,1,MPI_INT,m+1,0,MPI_COMM_WORLD);
                        printf("Msg sent from master to process: %i\n ", m+1);
                        row++;
                  }
               do
                 {

                        MPI_Recv(&temp_recvbuf,(800*3),MPI_INT,MPI_ANY_SOURCE,0,MPI_COMM_WORLD, &status);
                        row_rec=temp_recvbuf[0];
                        send1=row;

                        MPI_Send(&send1,1,MPI_INT,status.MPI_SOURCE,0,MPI_COMM_WORLD);
                        printf("MASTER:Second send to SLAVE %d",status.MPI_SOURCE);
                        row++;
                 

                   for(n=0;n<(800*3);n++)
                  {


                                                recvbuf[(row_rec*800*3)+n] = temp_recvbuf[n];
                                        
                                         printf("\nprinted:[%d]",recvbuf[(row_rec*800*3)+n]);
                  }
                                  printf("received message from process : %i \n",m+1);

               } while(row!=800 & row_rec!=800);


                                if (  (display = XOpenDisplay (display_name)) == NULL ) {
                                fprintf (stderr, "drawon: cannot connect to X server %s\n",
                                XDisplayName (display_name) );
                                exit (-1);
                                }



                                screen = DefaultScreen (display);
                                display_width = DisplayWidth (display, screen);
                                display_height = DisplayHeight (display, screen);



                                width = X_RESN;
                                height = Y_RESN;
                                x = 0;
                                y = 0;

                                 border_width = 4;
                                win = XCreateSimpleWindow (display, RootWindow (display, screen),
                                x, y, width, height, border_width,
                                BlackPixel (display, screen), WhitePixel (display, screen));

                                size_hints.flags = USPosition|USSize;
                                size_hints.x = x;
                                size_hints.y = y;
                                size_hints.width = width;
                                size_hints.height = height;
                                size_hints.min_width = 300;
                                size_hints.min_height = 300;

                                XSetNormalHints (display, win, &size_hints);
                                XStoreName(display, win, window_name);



                                gc = XCreateGC (display, win, valuemask, &values);

                                XSetBackground (display, gc, WhitePixel (display, screen));
                                XSetForeground (display, gc, BlackPixel (display, screen));
                                XSetLineAttributes (display, gc, 1, LineSolid, CapRound, JoinRound);

                                attr[0].backing_store = Always;
                                attr[0].backing_planes = 1;
                                attr[0].backing_pixel = BlackPixel(display, screen);

                                XChangeWindowAttributes(display, win, CWBackingStore | CWBackingPlanes | CWBackingPixel, attr);

                                XMapWindow (display, win);
                                XSync(display, 0);
                             for (u=0;u<1920000;u++)
                                {
                                point = (u*3)+2;
          if (recvbuf[point]==100)
                                  {
                                  //printf("\nprinted:[%d][%d]",recvbuf[u*3],recvbuf[(u*3)+1]);
                                  XDrawPoint (display, win, gc,recvbuf[u*3] , recvbuf[(u*3)+1]);
                                  }
                                }
                               XFlush(display);
                               sleep(50);
                }

else
                {
                                       do{
                                           MPI_Recv(&recv,1,MPI_INT,0,0,MPI_COMM_WORLD,&status);
                                           row=recv;
                                           printf("RECV:%d",recv);
                                           for(i=0; i < X_RESN; i++)
                                       
                                           {

                                                        z.real = z.imag = 0.0;
                                                        c.real = ((float) row - 400.0)/200.0;
                                                        c.imag = ((float) i - 400.0)/200.0;
                                                        k = 0;

                                                do  {

                                                                temp = z.real*z.real - z.imag*z.imag + c.real;
                                                                z.imag = 2.0*z.real*z.imag + c.imag;
                                                                z.real = temp;
                                                                lengthsq = z.real*z.real+z.imag*z.imag;
                                                                k++;

                                                        } while (lengthsq < 4.0 && k < 100);
                                        

                                                        sendbuf[i*3] = row;
                                                        sendbuf[(i*3) + 1] = i;


 sendbuf[(i*3) + 2] = k;
                                                }
                                                      
                                                        MPI_Send(&sendbuf, (800*3), MPI_INT, 0, 0, MPI_COMM_WORLD);
                                                        printf("Slave:%d Mssg sent to mastsr",rank);
                                                        for(j=0;j<((800*3)-1);j++)
                                                        printf("\nSLAVE:%d [SENTBUF]: %d",sendbuf[j+2]);
                } while(1);
}
MPI_Finalize();
return(0);
}
                                        